export namespace DataUtils {

  export interface Context{
    key?:string
    val?:any
    row?:any
    data:any
    list?:any[]
    ins?:number
    parents:any[]
  }

  export interface Rule {
    key?:string|RegExp|((k:string,context:Context) => string|boolean|void)|[s:string|RegExp|string[],t?:string|string[]]
    value?:string|((v:any,context:Context) => any);
    once?:boolean
    deep?:boolean
    methods?:[f:(context:Context) => void,exp?:string|((context:Context) => boolean)]
  }


  export class Date{
    static init(){
      
    }
    static format(){}
  }
  
  export class Layout{}

  
  
}


export namespace Tree {
  export interface IContext extends Record<string,any> {
    node:any
    list?:any[]
    i?:number
    parent?:any
    data:any
  }

  export interface IOptions extends Record<string,any> {
    children?:string
  }
  // 深度优先遍历
  export const DFS = <T>(data:T[],call?:(ctx:IContext) => boolean | void,options:IOptions = {}) => {
    const {children:ck = 'children'} = options
    const fn = (list:T[],parent?:T) => {
      for(let i = 0,l = list.length; i < l;i++){
        const d:any = list[i] || {};
        const ctx:IContext = {i,node:d,list,parent,data}
        //
        let res = true;
        if(call){
          res = call(ctx) ?? true;
        }
        if(res === false){
          break;
        }
        const cls = d[ck];
        if(cls && cls.length > 0){
          fn(cls,d); // 递归
        }
      }
    }
    // 调用
    fn(data)
  }
  // 广度优先遍历
  export const BFS = <T>(data:T[],call?:(ctx:IContext) => boolean | void,options:IOptions = {}) => {
    const {children:ck = 'children'} = options;
    const list = [...data];
    while(list.length > 0){
      const d:any = list.shift() || {};
      const ctx:IContext = {node:d,data}
      //
      let res = true;
      if(call){
        res = call(ctx) ?? true;
      }
      if(res === false){
        break;
      }
      //
      const cls:any[] = d[ck] || [];
      if(cls.length > 0){
        list.push(...cls);
      }
    }
  }
  //
  export const reset = <T>(data:T[]) => {
    
  }
}